﻿// Inner Fire 游戏引擎库
// 场景类
//
// Copyright (c) 2023 by 尔西大帝. All rights reserved.
//
// 这个类用于控制不同场景。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-25

#include "dx_scene.h"
#include <dx_scene/dx_scene.h>

///////////////////////////////////////////////////////////////////////////////
// 房间
///////////////////////////////////////////////////////////////////////////////
namespace ifire {
void DxScene::Update() {
  if (id_ == DxSceneID::ROOM) {
    graphics_->Room_Update();
  } else if (id_ == DxSceneID::WATER) {
    graphics_->MountainWater_Update();
  } else if (id_ == DxSceneID::VEC_ADD) {
    graphics_->VecAdd_InitPipeline();
  } else if (id_ == DxSceneID::TESS_BASIC || id_ == DxSceneID::TESS_PATCH) {
    graphics_->Tess_Update();
  } else if (id_ == DxSceneID::ALTAR) {
    graphics_->Altar_Update();
  } else if (id_ == DxSceneID::INSTANED) {
    graphics_->Instanced_Update();
  } else if (id_ == DxSceneID::PICK) {
    graphics_->Pick_Update();
  } else if (id_ == DxSceneID::CUBE) {
    graphics_->Cube_Update();
  } else if (id_ == DxSceneID::DYNAMIC_CUBE) {
    graphics_->DynamicCube_Update();
  } else if (id_ == DxSceneID::NORMAL) {
    graphics_->Normal_Update();
  } else if (id_ == DxSceneID::SHADOWS) {
    graphics_->Shadows_Update();
  } else if (id_ == DxSceneID::SSAO) {
    graphics_->Ssao_Update();
  } else if (id_ == DxSceneID::SKIN) {
    graphics_->Skin_Update();
  }
}

void DxScene::InitPipeline() {
  if (id_ == DxSceneID::ROOM) {
    graphics_->Room_InitPipeline();
  } else if (id_ == DxSceneID::WATER) {
    graphics_->MountainWater_InitPipeline();
  } else if (id_ == DxSceneID::VEC_ADD) {
    graphics_->VecAdd_InitPipeline();
  } else if (id_ == DxSceneID::TESS_BASIC || id_ == DxSceneID::TESS_PATCH) {
    graphics_->Tess_InitPipeline();
  } else if (id_ == DxSceneID::ALTAR) {
    graphics_->Altar_InitPipeline();
  } else if (id_ == DxSceneID::INSTANED) {
    graphics_->Instanced_InitPipeline();
  } else if (id_ == DxSceneID::PICK) {
    graphics_->Pick_InitPipeline();
  } else if (id_ == DxSceneID::CUBE) {
    graphics_->Cube_InitPipeline();
  } else if (id_ == DxSceneID::DYNAMIC_CUBE) {
    graphics_->DynamicCube_InitPipeline();
  } else if (id_ == DxSceneID::NORMAL) {
    graphics_->Normal_InitPipeline();
  } else if (id_ == DxSceneID::SHADOWS) {
    graphics_->Shadows_InitPipeline();
  } else if (id_ == DxSceneID::SSAO) {
    graphics_->Ssao_InitPipeline();
  } else if (id_ == DxSceneID::SKIN) {
    graphics_->Skin_InitPipeline();
  }
}

void DxScene::Draw() {
  if (id_ == DxSceneID::ROOM) {
    graphics_->Draw_Room();
  } else if (id_ == DxSceneID::WATER) {
    graphics_->MountainWater_Draw();
  } else if (id_ == DxSceneID::VEC_ADD) {
    graphics_->VecAdd_Draw();
  } else if (id_ == DxSceneID::TESS_BASIC || id_ == DxSceneID::TESS_PATCH) {
    graphics_->Tess_Draw();
  } else if (id_ == DxSceneID::ALTAR) {
    graphics_->Altar_Draw();
  } else if (id_ == DxSceneID::INSTANED) {
    graphics_->Instanced_Draw();
  } else if (id_ == DxSceneID::PICK) {
    graphics_->Pick_Draw();
  } else if (id_ == DxSceneID::CUBE) {
    graphics_->Cube_Draw();
  } else if (id_ == DxSceneID::DYNAMIC_CUBE) {
    graphics_->DynamicCube_Draw();
  } else if (id_ == DxSceneID::NORMAL) {
    graphics_->Normal_Draw();
  } else if (id_ == DxSceneID::SHADOWS) {
    graphics_->Shadows_Draw();
  } else if (id_ == DxSceneID::SSAO) {
    graphics_->Ssao_Draw();
  } else if (id_ == DxSceneID::SKIN) {
    graphics_->Skin_Draw();
  }
}

bool DxScene::IsTakeoverDraw() const {
  if (id_ == DxSceneID::ROOM) {
    return false;
  }
  return true;
}

bool DxScene::IsTakeoverRtvAndDsv() const {
  if (id_ == DxSceneID::SSAO || id_ == DxSceneID::SKIN) {
    return true;
  }
  return false;
}

void DxScene::DoComputeWork() {
  if (id_ == DxSceneID::VEC_ADD) {
    graphics_->VecAdd_DoComputeWork();
  }
}
void DxScene::OnKeyboardInput() {}
void DxScene::OnMouseMove(WPARAM state, int x, int y) {}

void DxScene::OnMouseDown(WPARAM state, int x, int y) {
  if (id_ == DxSceneID::PICK) {
    graphics_->Pick_OnMouseDown(state, x, y);
  }
}

void DxScene::OnMouseUp(WPARAM state, int x, int y) {}

void DxScene::CreateRtvAndDsvDescriptorHeaps() {
  int num_rtv = SwapChainBufferCount;
  int num_dsv = 1;

  if (id_ == DxSceneID::SSAO || id_ == DxSceneID::SKIN) {
    num_rtv = SwapChainBufferCount + 3;
    num_dsv = 2;
  }

  // Add +1 for screen normal map, +2 for ambient maps.
  D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
  rtvHeapDesc.NumDescriptors = num_rtv;
  rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  rtvHeapDesc.NodeMask = 0;
  ThrowIfFailed(graphics_->device_->CreateDescriptorHeap(
      &rtvHeapDesc, IID_PPV_ARGS(graphics_->rtv_heap_.GetAddressOf())));

  // Add +1 DSV for shadow map.
  D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
  dsvHeapDesc.NumDescriptors = num_dsv;
  dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  dsvHeapDesc.NodeMask = 0;
  ThrowIfFailed(graphics_->device_->CreateDescriptorHeap(
      &dsvHeapDesc, IID_PPV_ARGS(graphics_->dsv_heap_.GetAddressOf())));
}

} // namespace ifire
